package com.hzit.security.filter;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hzit.security.entity.LoginUser;
import com.hzit.security.vo.UserVo;
import com.hzit.util.R;
import lombok.SneakyThrows;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import static com.hzit.constant.CommonConstant.LOGIN_KEY_PREFIX;

/**
 * 功能：登录过滤器
 * 作者：WF
 */
public class HzitLoginFilter extends UsernamePasswordAuthenticationFilter {
	private AuthenticationManager authenticationManager;
	private StringRedisTemplate redisTemplate;

	public HzitLoginFilter( AuthenticationManager authenticationManager,StringRedisTemplate redisTemplate){
		this.authenticationManager = authenticationManager;
		this.redisTemplate = redisTemplate;
		this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/user/login", HttpMethod.POST.toString()));
	}

	//1. 登录认证
	@SneakyThrows
	@Override
	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
		//1.1 得到用户名及密码信息
		UserVo vo = new ObjectMapper().readValue(request.getInputStream(), UserVo.class);
		//1.2 构造一个需要认证的对象
		UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken(vo.getUsername(),vo.getPassword(),null);
		try {
			return authenticationManager.authenticate(upat);
		} catch (AuthenticationException e) {
			e.printStackTrace();
		}
		return null;
	}

	//2. 登录成功处理
	@Override
	protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
		//2.1 成功后，生成token值
		String token = UUID.randomUUID().toString().replace("-", "");
		LoginUser principal = (LoginUser) authResult.getPrincipal();

		//2.2 将token值放到redis中
		//2.2.1 生成rediskey
		String key = getKey(token);
		//2.2.2 写入redis
		redisTemplate.opsForValue().set(key, JSON.toJSONString(principal));

		//2.3 响应回前端
		Map<String,String> map = new HashMap<>();
		map.put("token",token);
		R<Map<String, String>> r = R.ok(map, "登录成功!");
		ResponseUtil.writeStr(response,JSON.toJSONString(r));
	}

	//3. 登录失败处理
	@Override
	protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
		R<Object> r = R.fail("登录认证失败!");
		ResponseUtil.writeStr(response,JSON.toJSONString(r));
	}

	//4. 获取redis的key
	private String getKey(String token) {
		return LOGIN_KEY_PREFIX + token;
	}
}
